package com.sunwayhorizo.health.business.registries.organization;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.dto.ResultsDTO;
import com.sunwayhorizo.health.business.dto.registries.DepartmentDTO;
import com.sunwayhorizo.health.business.registries.organization.query.DepartmentQueryLocal;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.AD;
import com.sunwayhorizo.health.hl7.datatypes.BAG_EN;
import com.sunwayhorizo.health.hl7.datatypes.CE;
import com.sunwayhorizo.health.hl7.datatypes.CS;
import com.sunwayhorizo.health.hl7.datatypes.ED;
import com.sunwayhorizo.health.hl7.datatypes.II;
import com.sunwayhorizo.health.hl7.datatypes.SET_II;
import com.sunwayhorizo.health.hl7.datatypes.common.ADXPImpl;
import com.sunwayhorizo.health.hl7.datatypes.common.CSImpl;
import com.sunwayhorizo.health.hl7.datatypes.common.ENImpl;
import com.sunwayhorizo.health.hl7.persistent.RimCoreRoles;
import com.sunwayhorizo.health.hl7.rim.ControlAct;
import com.sunwayhorizo.health.hl7.rim.Organization;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.vocabulary.ActCode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityAddrPartType;
import com.sunwayhorizo.health.hl7.vocabulary.EntityAddrUse;
import com.sunwayhorizo.health.hl7.vocabulary.EntityCode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityDeterminer;
import com.sunwayhorizo.health.hl7.vocabulary.EntityNameUse;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;
import com.sunwayhorizo.health.hl7.vocabulary.RoleClass;
import com.sunwayhorizo.health.hl7.vocabulary.RoleIICode;
import com.sunwayhorizo.health.hl7.vocabulary.SystemBusinessConstantsCode;

@Stateless
@Name("DepartmentManager")
public class DepartmentManager extends BaseManager implements DepartmentManagerLocal
{

    private DepartmentQueryLocal deptDaoManager = (DepartmentQueryLocal) Component.getInstance("DepartmentQuery");


    public ResultsDTO newDepartment(DepartmentDTO departmentDTO) throws Hl7Exception
    {
        //准备基本数据
        CE ce = null;
        CS cs = null;
        // 拿到科室类型 科室类型为空代码添加的为行政科室，科室类型不为空，代表添加的为工作组
        if (departmentDTO.getFlag().equals("2"))
        {
            // 工作组
            ce = getDataTypeFactory().newCE(EntityCode.WORKGROUP.toString());
            cs = ActCode.WORKGROUP;
        }
        if (departmentDTO.getFlag().equals("1"))
        {
            // 科室
            ce = getDataTypeFactory().newCE(EntityCode.DEPARTMENT.toString());
            cs = ActCode.DEPARTMENT;
        }

        Organization deptartment = null;
        if (StrUtil.isNotEmpty(departmentDTO.getDepartmentCode()))
        {
            deptartment = deptDaoManager.findOrganizationByCode(departmentDTO.getDepartmentCode());
        }
        if (null == deptartment)
        {
            deptartment = getEntityFactory().newOrganization(ce, EntityDeterminer.INSTANCE, null);
            converOrganizationToDepatmentDTO(deptartment, departmentDTO);
        }
        Organization org = null;
        // 父id
        if (StrUtil.isNotEmpty(departmentDTO.getParentId()))
        {
            org = (Organization)baseQuery.findHl7EntityById(Long.parseLong(departmentDTO.getParentId()));
        }
        if (org == null && StrUtil.isNotEmpty(departmentDTO.getParentCode()))
        {
            org = deptDaoManager.findDepartmentByCode(departmentDTO.getParentCode());
        }
        
        if (null != deptartment && null != org)
        {
            String extenID = em.createNativeQuery("select EXTEN_CODE.NEXTVAL from dual").getResultList().get(0).toString();
            SET_II oraId = DataTypeUtil.getSet_II(root, "org" + extenID, null, "DEPT");
            
            Role role = getRoleFactory().newRole(RoleClass.PART, ce, deptartment, org, oraId);
            // 设置科室角色属性
            converRoleToDepartmentDTO(role, departmentDTO);
            
            ControlAct controlAct = newControlAct(cs, ParticipationType.SBJ, extenID, role);
            
            em.persist(controlAct);
            log.info("新增科室成功:" + role.getRoleId());
            return getResultsDTO("新增成功", true, deptartment.getEntityId());
        }
        else
        {
            return getResultsDTO("新增不成功", true, null);
        }
    }


    @SuppressWarnings("rawtypes")
    public ResultsDTO delDepartment(List depIds) throws Hl7Exception
    {
        log.info("删除机构数组大小为" + depIds.size());
        if (ListUtil.isNotEmpty(depIds))
        {
            boolean isOrg = deptDaoManager.findDepartByDeptIds(depIds);
            if (isOrg)
            {
                return getResultsDTO("不能删除,机构下面已有科室", true, "");
            }
            boolean isPerson = deptDaoManager.findPersonByOrgIds(depIds);
            if (isPerson)
            {
                return getResultsDTO("不能删除，机构下面已有人员", true, "");
            }
            List<Role> listOrg = deptDaoManager.findListOrg(depIds);
            if (ListUtil.isNotEmpty(listOrg))
            {
                for (Role role : listOrg)
                {
                    em.remove(role.getPlayerEntity());
                    em.remove(role);
                    log.info("删除科室成功");
                }
            }
        }
        return  getResultsDTO("删除成功", true, "");
    }


    public ResultsDTO updateDepartment(DepartmentDTO departmentDTO) throws Hl7Exception
    {
        if (null == departmentDTO || StrUtil.isEmpty(departmentDTO.getRimDepartmentRoleId()))
            return this.getResultsDTO("科室信息为空，不能修改", true, null);
        
        Role deptRole = baseQuery.findRoleById(Long.parseLong(departmentDTO.getRimDepartmentRoleId()));
        
        if (null != deptRole)
        {
            // 科室类型
            CE deptType = this.getDictionaryFactory().getCeByDictionaryDTO(departmentDTO.getDepartmentType());
            deptRole.setTypeCodeEts(deptType);
            
            Organization deptartment = (Organization) deptRole.getPlayerEntity();
            converOrganizationToDepatmentDTO(deptartment, departmentDTO);
            
            em.merge(deptRole);
            log.info("【修改科室成功】");
        }
        return getResultsDTO("更新科室成功", true, null);
    }


    public ResultsDTO findDepartmentTree(String orgId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(orgId))
            return this.getResultsDTO("机构编码为空，拿不到对应的科室", true, null);
        ResultsDTO resultsDTO = null;
        long start = System.currentTimeMillis();
        List<Role> list = deptDaoManager.findDepartmentOrWorkGroupByOrgId(orgId);
        long seach = System.currentTimeMillis();
        log.info("【查询耗时为】：" + (seach - start) + "毫秒");
        List<DepartmentDTO> topCategorys = converTreeList(list, orgId);
        long end = System.currentTimeMillis();
        if (ListUtil.isNotEmpty(topCategorys))
        {
            resultsDTO = getResultsDTO("查询成功", true, topCategorys);
            log.info("【总共组装树时间为】：" + (end - seach));
        }
        else
        {
            resultsDTO = getResultsDTO("没有查询到记录", true, "");
        }
        return resultsDTO;
    }


    public ResultsDTO findActiveDepartmentTree(String orgId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(orgId))  return this.getResultsDTO("机构编码为空，拿不到对应的科室", true, null);
        
        ResultsDTO resultsDTO = null;
        
        long start = System.currentTimeMillis();
        List<Role> list = deptDaoManager.findActiveDeptOrWgByOrgId(orgId);
        long seach = System.currentTimeMillis();
        log.info("【查询耗时为】：" + (seach - start) + "毫秒");
        
        List<DepartmentDTO> topCategorys = converTreeList(list, orgId);
        long end = System.currentTimeMillis();
        if (ListUtil.isNotEmpty(topCategorys))
        {
            resultsDTO = getResultsDTO("查询成功", true, topCategorys);
            log.info("【总共组装树时间为】：" + (end - seach));
        }
        else
        {
            resultsDTO = getResultsDTO("没有查询到记录", true, "");
        }
        return resultsDTO;
    }


    public ResultsDTO validateDeptCode(String code) throws Hl7Exception
    {
        boolean flag = baseQuery.findRimCoreRoleIiByCode(code);
        if (flag)
        {
            return this.getResultsDTO("科室code不重复", true, "1");
        }
        else
            return this.getResultsDTO("科室code重复", true, "0");
    }


    public ResultsDTO findOnlyDepartmentTree(String orgId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(orgId))
            return this.getResultsDTO("机构编码为空，拿不到对应的科室", true, null);
        ResultsDTO resultsDTO = null;
        long start = System.currentTimeMillis();
        List<Role> list = deptDaoManager.findOnlyDepartment(orgId);
        long seach = System.currentTimeMillis();
        log.info("【查询耗时为】：" + (seach - start) + "毫秒");
        List<DepartmentDTO> topCategorys = converTreeList(list, orgId);
        long end = System.currentTimeMillis();
        if (ListUtil.isNotEmpty(topCategorys))
        {
            resultsDTO = getResultsDTO("查询成功", true, topCategorys);
            log.info("【总共组装树时间为】：" + (end - seach));
        }
        else
        {
            resultsDTO = getResultsDTO("没有查询到记录", true, null);
        }
        return resultsDTO;
    }


    public ResultsDTO findWorkGroupList() throws Hl7Exception
    {
        List<Role> list = deptDaoManager.findWorkGroupAll();
        if (ListUtil.isNotEmpty(list))
        {
            List<DepartmentDTO> departmentDTOList = converDepartmentDTOListByDeptRoleList(list);
            return this.getResultsDTO("查询工作组成功", true, departmentDTOList);
        }
        else
            return this.getResultsDTO("没有找到相应的工作组", true, null);
    }


    public ResultsDTO findInHospitalWorkGroupList() throws Hl7Exception
    {
        List<Role> list = deptDaoManager.findRoleListByCond(SystemBusinessConstantsCode.DEPART_ATTR_DIC.getValue(), "2");
        if (ListUtil.isNotEmpty(list))
        {
            List<DepartmentDTO> departmentDTOList = converDepartmentDTOListByDeptRoleList(list);
            return this.getResultsDTO("查询工作组成功", true, departmentDTOList);
        }
        else
            return this.getResultsDTO("没有找到相应的工作组", true, null);
    }


    public ResultsDTO findOutHospitalWorkGroupList() throws Hl7Exception
    {
        List<Role> list = deptDaoManager.findRoleListByCond(SystemBusinessConstantsCode.DEPART_ATTR_DIC.getValue(), "0");
        if (ListUtil.isNotEmpty(list))
        {
            List<DepartmentDTO> departmentDTOList = converDepartmentDTOListByDeptRoleList(list);
            return this.getResultsDTO("查询工作组成功", true, departmentDTOList);
        }
        else
            return this.getResultsDTO("没有找到相应的工作组", true, null);
    }


    public ResultsDTO findWorkGroupListByType(String codingSchemesEnName, String conceptCode) throws Hl7Exception
    {
        List<Role> list = deptDaoManager.findRoleListByCond(codingSchemesEnName, conceptCode);
        if (ListUtil.isNotEmpty(list))
        {
            List<DepartmentDTO> departmentDTOList = converDepartmentDTOListByDeptRoleList(list);
            return this.getResultsDTO("查询工作组成功", true, departmentDTOList);
        }
        else
            return this.getResultsDTO("没有找到相应的工作组", true, null);
    }
    public DepartmentDTO converDepartmentDTOByDeptRole(Role role) throws Hl7Exception
    {
        if(role == null) return null;
        DepartmentDTO departmentDTO = new DepartmentDTO();
        if (null != role.getPlayerEntities())
        {
            // 拿到科室的play
            departmentDTO = convertDepartmentDTO((Organization)role.getPlayerEntities()); 
                                                                            // Entity信息
        }
        converDepartmentDTOToRole(role, departmentDTO); // 拿到科室的角色信息
        return departmentDTO;
    }
    
    @SuppressWarnings("rawtypes")
    public DepartmentDTO convertDepartmentDTO(Organization entitys) throws Hl7Exception
    {
        if (null == entitys) return null;
        DepartmentDTO dto = new DepartmentDTO();
        
        // 科室 RIM EntityId
        dto.setDepartmentId(entitys.getEntityId().toString());

        //dept名称
        BAG_EN names =  entitys.getName();
        if(names != null)
        {
            List mList = names.toList();
            for(int i=0; i<mList.size(); i++)
            {
                ENImpl en = (ENImpl) mList.get(i);
                Set set = (Set) en.use().toSet();
                String code = "";
                if(!set.isEmpty())
                {
                    CSImpl use = (CSImpl) set.iterator().next();
                    code = use.code().toString();
                }
                if(code.equals(EntityNameUse.L.code().toString()))
                {
                    dto.setDepartmentName(en.formatted().toString());
                }
                if(code.equals(EntityNameUse.PHON.code().toString()))
                {
                    dto.setPinyinCode(en.formatted().toString());
                }
                if(code.equals(EntityNameUse.SNDX.code().toString()))
                {
                    dto.setWubiCode(en.formatted().toString());
                }
            }
        }

        // 位置
        AD addrs = entitys.getAddr();
        if(null != addrs)
        {
            List mList = addrs.toList();
            for (int i = 0; i < mList.size(); i++)
            {
                
                ADXPImpl ad = (ADXPImpl) mList.get(i);
                String type = ad.partType().code().toString();
                if(type.equals(EntityAddrPartType.ORGADDRS.code().toString()))
                {
                    dto.setPosition(ad.literal().toString());
                }
            }
        }
        
        // 备注
        if (entitys.getDesc() != null)
        {
            dto.setDescription((!entitys.getDesc().literal().toString().equals("<Null:NullFlavor: NI>") ? entitys.getDesc().literal().toString() : ""));
        }

        return dto;
    }

    //根据科室角色集合组装科室DTO集合
    private List<DepartmentDTO> converDepartmentDTOListByDeptRoleList(List<Role> list) throws Hl7Exception
    {
        if (ListUtil.isEmpty(list)) return null;
        
        List<DepartmentDTO> deptList = new ArrayList<DepartmentDTO>();
        for (Role role : list)
        {
            DepartmentDTO departmentDTO = new DepartmentDTO();
            if (null != role.getPlayerEntities())
            {
                // 拿到科室的playEntity信息
                departmentDTO = convertDepartmentDTO((Organization)role.getPlayerEntities()); 
            }
            // 拿到科室的角色信息
            converDepartmentDTOToRole(role, departmentDTO);
            deptList.add(departmentDTO);
        }
        return deptList;
    }


    //根据科室dto组装Organization
    private void converOrganizationToDepatmentDTO(Organization organization, DepartmentDTO departmentDTO) throws Hl7Exception
    {
            // 科室名称
            String orgenType[] = { null };
            String orgenNameUseCode = "";
            if (StrUtil.isNotEmpty(departmentDTO.getDepartmentName()))
            {
                String deptName = departmentDTO.getDepartmentName();
                String[] orgenName = { deptName };
                orgenNameUseCode = EntityNameUse.L.code().toString();
                BAG_EN bagEnName = DataTypeUtil.getBagEN(orgenName, orgenType, orgenNameUseCode);
                organization.setName(bagEnName);
            }

            // 拼音码
            if (StrUtil.isNotEmpty(departmentDTO.getPinyinCode()))
            {
                String yinwm = departmentDTO.getPinyinCode();
                String yin[] = { yinwm };
                orgenNameUseCode = EntityNameUse.PHON.code().toString();
                BAG_EN yinwmName = DataTypeUtil.getBagEN(yin, orgenType, orgenNameUseCode);
                organization.setName(yinwmName);
            }

            // 五笔码
            if (StrUtil.isNotEmpty(departmentDTO.getWubiCode()))
            {
                String wbm = departmentDTO.getWubiCode();
                String wb[] = { wbm };
                orgenNameUseCode = EntityNameUse.SNDX.code().toString();
                BAG_EN yinwmName = DataTypeUtil.getBagEN(wb, orgenType, orgenNameUseCode);
                organization.setName(yinwmName);
            }

            // 位置
            if (StrUtil.isNotEmpty(departmentDTO.getPosition()))
            {
                String[] addr = new String[1];
                addr[0] = departmentDTO.getPosition();
                String[] addrPart = { EntityAddrPartType.ORGADDRS.code().toString() };
                AD ad = DataTypeUtil.getAD(addr, addrPart, EntityAddrUse.H.code().toString());
                organization.setAddr(ad);
            }

        // 描述
        if (StrUtil.isNotEmpty(departmentDTO.getDescription()))
        {
            ED desc = DataTypeUtil.getED(departmentDTO.getDescription());
            organization.setDesc(desc);
        }
    }


    //设置科室角色的固有属性
    private void converRoleToDepartmentDTO(Role deptRole, DepartmentDTO departmentDTO) throws Hl7Exception
    {
        if (StrUtil.isNotEmpty(departmentDTO.getState()))
        {
            // 科室状态 0：启用 1：停用
            deptRole.setStatusCode(DataTypeUtil.getCS(departmentDTO.getState()));
        }
        // 科室类型
        if (departmentDTO.getFlag().equals("2"))
        {
            if (null != departmentDTO.getDepartmentType() && StrUtil.isNotEmpty(departmentDTO.getDepartmentType().getConceptCode()))
            {
                CE deptType = this.getDictionaryFactory().getCeByDictionaryDTO(departmentDTO.getDepartmentType());
                deptRole.setTypeCodeEts(deptType);
            }
        }
        // 科室编码
        if (StrUtil.isNotEmpty(departmentDTO.getDepartmentCode()))
        {
            II id = DataTypeUtil.getII(root, departmentDTO.getDepartmentCode(),"true", RoleIICode.DEPTCODE.toString());
            deptRole.setId(id);
        }
    }
    
    //把科室角色信息转化为科室dto对应属性
    private void converDepartmentDTOToRole(Role role, DepartmentDTO departmentDTO) throws Hl7Exception
    {
        // 拿到科室类型
        departmentDTO.setDepartmentType(getDictionaryFactory().getDictionaryDTOByCe(role.getTypeCodeEts()));
      
        // 拿到科室code
        II ii = role.getId(RoleIICode.DEPTCODE);
        departmentDTO.setDepartmentCode( ii != null && ii.extension()!=null ? ii.extension().toString() : null);
        
        // 设置科室角色id
        departmentDTO.setRimDepartmentRoleId(role.getRoleId().toString()); 
    }

    //根据科室属性数据源组装tree
    private List<DepartmentDTO> converTreeList(List<Role> list, String orgId) throws Hl7Exception
    {
        if (ListUtil.isNotEmpty(list))
        {
            List<DepartmentDTO> all = new ArrayList<DepartmentDTO>();

            // 将所子节点都加进来，设置父节点id
            for (RimCoreRoles role : list)
            {

                Organization scope = (Organization)role.getScoperEntities();
                Organization plyer = (Organization)role.getPlayerEntities();

                DepartmentDTO father = convertDepartmentDTO(scope);
                DepartmentDTO child = convertDepartmentDTO(plyer);
                converDepartmentDTOToRole((Role) role, child);// 设置科室角色属性
                // 判断是科室还是工作组
                String code = role.getCode().code().toString();
                if (StrUtil.isNotEmpty(code))
                {
                    if (code.equals(EntityCode.WORKGROUP.toString()))
                    {
                        child.setFlag("2");
                        father.setFlag("2");
                    }
                    if (code.equals(EntityCode.DEPARTMENT.toString()))
                    {
                        child.setFlag("1");
                        if (null != father)
                        {
                            father.setFlag("1");
                        }
                    }
                }
                if (father != null && child != null)
                {
                    if (father.getDepartmentId().equals(child.getDepartmentId()))
                    {
                        // 如果它既是Player又是Scoper
                        child.setParentId(null);
                        child.setFlag("0");
                        father.setFlag("0");
                    }
                    else
                    {
                        child.setParentId(father.getDepartmentId()); // 设置父亲节点id
                    }
                    all.add(child);
                }
            }

            List<DepartmentDTO> topCategorys = new ArrayList<DepartmentDTO>();
            for (DepartmentDTO cat : all)
            {
                // 如果父节点Id为空，则其为顶级节点 并且顶级节点只有一个单位
                if ((cat.getParentId() == null || cat.getParentId().equals("")) && cat.getDepartmentId().equals(orgId))
                {
                    topCategorys.add(cat);
                }
            }

            // 移除顶级节点
            for (DepartmentDTO top : topCategorys)
            {
                all.remove(top);
            }

            // 构建分类树
            buildCategoryTree(topCategorys, all);
            log.info("【数据条数为】：" + all.size());
            return topCategorys;
        }
        return null;
    }


    private void buildCategoryTree(List<DepartmentDTO> topCategorys, List<DepartmentDTO> categoryList)
    {
        if (null == categoryList)
        {
            return;
        }

        for (DepartmentDTO father : topCategorys)
        {
            List<DepartmentDTO> children = new ArrayList<DepartmentDTO>();
            for (DepartmentDTO child : categoryList)
            {
                // 如果这孩子没爹
                if (StrUtil.isNotBlank(child.getParentId()))
                {
                    // 有爹的时候才去判断父子关系
                    if (father.getDepartmentId().equals(child.getParentId()))
                    {

                        // 是父子节点关系
                        children.add(child);
                    }
                }
            }
            if (!children.isEmpty())
            {

                // 如果顶级节点有子节点，则需要递归层层构建子节点
                father.setChildren(children);

                // 递归构建
                buildCategoryTree(children, categoryList);
            }
        }
    }

}
